1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
| /** ****************************************************************************** * @file * @author maky <chengwei920412@outlook.com> * @version * @date 2018-01-04 16:22:58 * @brief ****************************************************************************** * @attention * * ****************************************************************************** */ #include <iostream> #include <Eigen/Eigen> #include <Eigen/geometry> #include <opencv2/opencv.hpp> #include <opencv2/aruco.hpp> #include <opencv2/core/eigen.hpp>
cv::Mat findHomography(const std::vector<cv::Point2f> &xs1, const std::vector<cv::Point2f> &xs2) { if (xs1.size() != xs2.size()) { return cv::Mat(); } int size = xs1.size(); Eigen::Matrix<double, Eigen::Dynamic, 9> A = Eigen::MatrixXd::Zero(2 * size, 9); for (auto pos = 0; pos < size; pos++) { auto &x1 = xs1.at(pos); auto &x2 = xs2.at(pos); auto rowx = pos * 2; auto rowy = rowx + 1; A(rowx, 0) = x1.x; A(rowx, 1) = x1.y; A(rowx, 2) = 1; A(rowx, 6) = -1 * x1.x * x2.x; A(rowx, 7) = -1 * x1.y * x2.x;
A(rowy, 3) = x1.x; A(rowy, 4) = x1.y; A(rowy, 5) = 1; A(rowy, 6) = -1 * x1.x * x2.y; A(rowy, 7) = -1 * x1.y * x2.y;
A(rowx, 8) = -1 * x2.x; A(rowy, 8) = -1 * x2.y; } Eigen::JacobiSVD<Eigen::Matrix<double, Eigen::Dynamic, 9>> solver(A, Eigen::ComputeFullV); const Eigen::VectorXd x = solver.matrixV().rightCols(1); Eigen::Matrix3d h; h << x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8]; h.normalize(); cv::Mat homography; cv::eigen2cv(h, homography); return homography; }
int main(int argc, const char **argv) { cv::Mat source = cv::imread("1546583988066087246-1.png"); cv::Mat patch = cv::imread("patch.png"); auto dictionary = cv::aruco::getPredefinedDictionary(cv::aruco::DICT_6X6_250); cv::Ptr<cv::aruco::DetectorParameters> parameters = cv::aruco::DetectorParameters::create(); // detect std::vector<int> ids; std::vector<std::vector<cv::Point2f>> corners, rejected_candidates; cv::aruco::detectMarkers(source, dictionary, corners, ids, parameters, rejected_candidates);
std::vector<cv::Point2f> patch_points; patch_points.push_back(cv::Point2f(0., 0.)); patch_points.push_back(cv::Point2f(patch.cols - 1, 0.)); patch_points.push_back(cv::Point2f(patch.cols - 1, patch.rows - 1)); patch_points.push_back(cv::Point2f(0., patch.rows - 1));
//cv::Mat homography = cv::findHomography(patch_points, corners[0]); cv::Mat homography = findHomography(patch_points, corners[0]); cv::Mat output; cv::warpPerspective(patch, output, homography, source.size());
for (auto u = 0; u < source.cols; u++) { for (auto v = 0; v < source.rows; v++) { auto pixel = output.at<cv::Vec3b>(v, u); if (pixel[0] != 0 || pixel[1] != 0 || pixel[2] != 0) { source.at<cv::Vec3b>(v, u) = pixel; } } } cv::imwrite("patched.png", source); cv::imshow("source", source); cv::imshow("patch", patch); cv::imshow("output", output);
while (true) { auto key = cv::waitKey(1); if (' ' == key) { break; } } return 0; }
|